import io
from typing import List

import PyPDF2

from model import Discipline

_FILE_PATH = "../backup/GBT 13745-2009.pdf"
_ROOT_DISCIPLINE = "知识"
_SCI_CATEGORIES = {
    "自然科学": (110, 190),
    "农业科学": (210, 240),
    "医药科学": (310, 360),
    "工程与技术科学": (410, 630),
    "人文与社会科学": (710, 910)
}


def get_sci_name(code: str):
    try:
        c = int(code)
        for k, v in _SCI_CATEGORIES.items():
            if v[0] <= c <= v[1]:
                return k
    except ValueError:
        return None


def is_code(s):
    try:
        float(s)
        return True
    except ValueError:
        return False


def decode_code(c: str):
    if len(c) == 3:
        return c, None, None
    if len(c) == 6:
        return c[:3], c[4:6], None
    return c[:3], c[4:6], c[6:]


def valid_code(c: tuple):
    return c[1] != "99" and c[2] != "99"


def process_pdf(filename):
    try:
        with open(filename, 'rb') as file:
            reader = PyPDF2.PdfReader(file)
            text_content = io.StringIO()  # 使用StringIO代替字符串拼接
            for page in reader.pages:
                text = page.extract_text()
                text_content.write(text)  # 将各页文本写入StringIO
                for line in text.split('\n'):
                    str_array = (s for s in line.split(" ") if s)  # 使用生成器表达式
                    for s in str_array:
                        yield s  # 将处理后的字符串作为生成器的输出
    except Exception as e:
        # 实际应用中应使用更详细的异常处理逻辑，并记录异常
        print(f"Error processing PDF: {filename}, {e}")
        return


def add_cat(data, code_dict, code, name):
    if code[1] is None:
        # 一级学科
        sci_name = get_sci_name(code[0])
        data[sci_name][name.strip()] = {}
    elif code[2] is None:
        sci_name = get_sci_name(code[0])
        first_c_name = code_dict[(code[0], None, None)]
        data[sci_name][first_c_name][name.strip()] = []
    else:
        sci_name = get_sci_name(code[0])
        first_c_name = code_dict[(code[0], None, None)]
        second_c_name = code_dict[(code[0], code[1], None)]
        data[sci_name][first_c_name][second_c_name].append(name.strip())


def get_data(filename):
    # 初始化变量
    code = None
    name = ""
    code_dict = {}
    data = {}
    # 添加所有学科的根节点
    for k, v in _SCI_CATEGORIES.items():
        data[k] = {}
    # 使用生成器处理PDF
    for s in process_pdf(filename):
        if is_code(s):
            if code is not None:
                if valid_code(code):
                    code_dict[code] = name.strip()
                    add_cat(data, code_dict, code, name.strip())
            code = decode_code(s)
            name = ""
        else:
            name += s
    # 处理最后一个条目
    if code is not None:
        if valid_code(code):
            code_dict[code] = name.strip()
            add_cat(data, code_dict, code, name.strip())
    return data


def generate() -> List[Discipline]:
    result = [Discipline(name=_ROOT_DISCIPLINE, category=_ROOT_DISCIPLINE, discipline_level=0)]
    for sci, fir_cats in get_data(_FILE_PATH).items():
        result.append(Discipline(name=sci, category=sci, super_disciplines=[_ROOT_DISCIPLINE], discipline_level=1))
        for fir_cat, sec_cats in fir_cats.items():
            result.append(Discipline(name=fir_cat, category=sci, super_disciplines=[sci], discipline_level=2))
            for sec_cat, thr_cats in sec_cats.items():
                result.append(Discipline(name=sec_cat, category=sci, super_disciplines=[sci, fir_cat], discipline_level=3))
                for thr_cat in thr_cats:
                    result.append(
                        Discipline(name=thr_cat, category=sci, super_disciplines=[sci, fir_cat, sec_cat], discipline_level=4))
    for discipline in result:
        discipline.source.append("名称、层级关系来源 GB/T 13745-2009 标准")
    return result


if __name__ == '__main__':
    import json

    base_data = generate()
    base_data = [d.model_dump_json() for d in base_data]
    with open("../assets/base_data.json", "w", encoding="utf-8") as f:
        json.dump(base_data, f)
